home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / jaq / dist / jaquith.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-26  |  30.8 KB  |  1,249 lines

  1. /* 
  2.  * jaquith.c --
  3.  *
  4.  *    Coordinator for the Jaquith archive system.
  5.  *
  6.  * Copyright 1991 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  *
  15.  * Quote:
  16.  *      "Beware of the man who works hard to learn something, learns it,
  17.  *      and finds himself no wiser than before," Bokonon tells us.  "He
  18.  *      is full of murderous resentment of people who are ignorant with-
  19.  *      out having come by their ignorance the hard way."
  20.  *      -- Kurt Vonnegut, _Cat's Cradle_
  21.  *
  22.  */
  23.  
  24. #ifndef lint
  25. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/jaquith.c,v 1.0 91/01/07 18:02:37 mottsmth Exp $ SPRITE (Berkeley)";
  26. #endif /* not lint */
  27.  
  28. #include "jaquith.h"
  29. #include "jaquithInt.h"
  30. #include "option.h"
  31.  
  32. int syserr;
  33. int jDebug;
  34.  
  35. static Parms parms = {
  36.     DEF_DETAIL,
  37.     DEF_JAQLOG,
  38.     DEF_PORT,
  39.     DEF_ROOT,
  40.     DEF_DEFARCH,
  41.     DEF_CONFIG, /* presently unused */
  42.     DEF_GET,
  43.     DEF_PUT,
  44.     DEF_CLEAN,
  45.     DEF_STATUS,
  46.     DEF_CHILDDBG,
  47.     DEF_DISKLOW,
  48.     DEF_DISKHIGH,
  49.     DEF_NETMASK,
  50.     DEF_FSYNCFREQ
  51. };
  52.  
  53. Option optionArray[] = {
  54.     {OPT_INT, "logdetail", (char *)&parms.logDetail, "set logging detail (1 2 4 8)"},
  55.     {OPT_INT, "port", (char *)&parms.port, "Port to listen on"},
  56.     {OPT_STRING, "root", (char *)&parms.root, "Root of index"},
  57.     {OPT_STRING, "logfile",(char *)&parms.logFile, "Enable logging to file"},
  58.     {OPT_STRING, "config", (char *)&parms.config, "Configuration file"},
  59.     {OPT_STRING, "getexec", (char *)&parms.getExec, "Jfetch exec path"},
  60.     {OPT_STRING, "putexec", (char *)&parms.putExec, "Jupdate exec path"},
  61.     {OPT_STRING, "cleanexec", (char *)&parms.cleanExec, "Jclean exec path"},
  62.     {OPT_STRING, "statexec", (char *)&parms.statExec, "Jquery exec path"},
  63.     {OPT_TRUE, "childdbg", (char *)&parms.childDbg, "Spawn children with debug"},
  64.     {OPT_STRING, "disklow", (char *)&parms.diskLow, "Low percent of disk that can be used"},
  65.     {OPT_STRING, "diskhigh", (char *)&parms.diskHigh, "High percent of disk that can be used"},
  66.     {OPT_STRING, "netmask", (char *)&parms.netMask, "Mask to restrict inet connections. Form: 128.32.*.*"},
  67.     {OPT_INT, "fsyncfreq", (char *)&parms.fsyncFreq, "Tell jupdate to fsync every N files"},
  68.     {OPT_TRUE, "test", (char *)&parms.test, "Run in test mode. Local connections only"},
  69. };
  70. int numOptions = sizeof(optionArray) / sizeof(Option);
  71.  
  72. /* File globals. */
  73. static char printBuf[T_MAXSTRINGLEN];
  74. static TClient *clientList[MAXCLIENT];
  75. static int clientMax = MAXCLIENT;
  76. static int deadChild = 0;
  77. static QInfo *qList = NULL;
  78. static char *progList[5] = { NULL, NULL, NULL, NULL, NULL };
  79. static FILE *memDbg;          /* stream for memory tracing */
  80.  
  81. /* The functions to be found here */
  82. static void     CheckOptions   _ARGS_ ((Parms *parmsPtr));
  83. static void     MakeRoot       _ARGS_ ((char *root));
  84. static void     PerformLoop    _ARGS_ ((int sock));
  85. static int      ReadMsg        _ARGS_ ((TClient *clientPtr));
  86. static int      ReadMsgHdr     _ARGS_ ((TClient *clientPtr));
  87. static int      ReadMsgBody    _ARGS_ ((TClient *clientPtr));
  88. static int      AddClient      _ARGS_ ((int sock));
  89. static void     DelClient      _ARGS_ ((TClient *clientPtr));
  90. static int      FindClientByPid _ARGS_ ((int pid));
  91. static TClient *FindClientBySocket _ARGS_ ((int sock));
  92. static void     ReapChild      _ARGS_ (());
  93. static void     SigChldHandler _ARGS_ ((int sig));
  94. static void     InstallHandlers _ARGS_ (());
  95. static void     StartManagers  _ARGS_ (());
  96. static void     RemoveLocks    _ARGS_ ((char *root));
  97. static int      CheckAuth      _ARGS_ ((AuthHandle handle));
  98. static void     ProcessCmd     _ARGS_ ((TClient *clientPtr));
  99. static void     SpawnChild     _ARGS_ ((TClient *clientPtr));
  100. static QInfo   *FindQueueInfo  _ARGS_ ((char *archName));
  101. static QInfo   *MakeQueueInfo  _ARGS_ ((char *archName));
  102. static void     SendMailResp   _ARGS_ ((TClient *clientPtr,
  103.                     int status, int syserr));
  104.  
  105.  
  106. /*
  107.  *----------------------------------------------------------------------
  108.  *
  109.  * main --
  110.  *
  111.  *    Jaquith is the coordinator program for the archive system.
  112.  *      It spawns jfetch, jupdate and jquery to carry out client requests.
  113.  *
  114.  * Results:
  115.  *    None.
  116.  *
  117.  * Side effects:
  118.  *    None.
  119.  *
  120.  *----------------------------------------------------------------------
  121.  */
  122.  
  123. void
  124. main(argc, argv)
  125.     int argc;                 /* main command line argument count */
  126.     char *argv[];             /* main command line arguments */
  127. {
  128.     int earSocket;
  129.     int i;
  130.  
  131. /*    memDbg = fopen("jaquith.mem","w"); */
  132.     MEM_CONTROL(8192, memDbg, TRACEMEM+TRACECALLS, 4096);
  133.  
  134.     for (i=0; i<clientMax; i++) {
  135.     clientList[i] = (TClient *)NULL;
  136.     }
  137.  
  138.     argc = Opt_Parse(argc, argv, optionArray, numOptions, 0);
  139.  
  140.     CheckOptions(&parms);
  141.  
  142.     MakeRoot(parms.root);
  143.  
  144.     InstallHandlers();
  145.  
  146.     StartManagers();
  147.  
  148.     RemoveLocks(parms.root);
  149.  
  150.     earSocket = Sock_SetupEarSocket(&parms.port);
  151.  
  152.     PerformLoop(earSocket); 
  153.  
  154.     exit(0);
  155. }
  156.  
  157.  
  158. /*
  159.  *----------------------------------------------------------------------
  160.  *
  161.  * CheckOptions --
  162.  *
  163.  *    Validate and install parameters
  164.  *
  165.  * Results:
  166.  *    None.
  167.  *
  168.  * Side effects:
  169.  *    None.
  170.  *
  171.  *----------------------------------------------------------------------
  172.  */
  173.  
  174. static void
  175. CheckOptions(parmsPtr)
  176.     Parms *parmsPtr;          /* pointer to parameter block */
  177. {
  178.     int val;
  179.     struct in_addr hostaddr;
  180.     struct hostent *hostPtr;
  181.     char hostname[T_MAXSTRINGLEN];
  182.  
  183.     if ((parmsPtr->port <= 0) || (parmsPtr->port > MAXPORT)) {
  184.     Utils_Bailout("CheckOptions: bad port number.\n",BAIL_PRINT);
  185.     }
  186.     if (parmsPtr->logFile != (char *)NULL) {
  187.     Log_Open(parmsPtr->logFile);
  188.     Log_SetDetail(parmsPtr->logDetail);
  189.     }
  190.     if (parmsPtr->root[0] != '/') {
  191.     Utils_Bailout("CheckOptions: root must be an absolute path.\n",
  192.               BAIL_PRINT);
  193.     }
  194.     if (access(parmsPtr->getExec, X_OK) == -1) {
  195.     sprintf(printBuf, "CheckOptions: can't find or access %s\n",
  196.         parmsPtr->getExec, X_OK);
  197.     Utils_Bailout(printBuf, BAIL_PRINT);
  198.     }
  199.     if (access(parmsPtr->putExec, X_OK) == -1) {
  200.     sprintf(printBuf, "CheckOptions: can't find or access %s\n",
  201.         parmsPtr->putExec, X_OK);
  202.     Utils_Bailout(printBuf, BAIL_PRINT);
  203.     }
  204.     if (access(parmsPtr->cleanExec, X_OK) == -1) {
  205.     sprintf(printBuf, "CheckOptions: can't find or access %s\n",
  206.         parmsPtr->cleanExec, X_OK);
  207.     Utils_Bailout(printBuf, BAIL_PRINT);
  208.     }
  209.     if (access(parmsPtr->statExec, X_OK) == -1) {
  210.     sprintf(printBuf, "CheckOptions: can't find or access %s\n",
  211.         parmsPtr->statExec, X_OK);
  212.     Utils_Bailout(printBuf, BAIL_PRINT);
  213.     }
  214.     progList[T_CMDLS] = parmsPtr->getExec;
  215.     progList[T_CMDGET] = parmsPtr->getExec;
  216.     progList[T_CMDPUT] = parmsPtr->putExec;
  217.     progList[T_CMDSTAT] = parmsPtr->statExec;
  218.     if ((Utils_CvtInteger(parmsPtr->diskLow, 0, 100, &val) != T_SUCCESS) ||
  219.     (Utils_CvtInteger(parmsPtr->diskHigh, 0, 100, &val) != T_SUCCESS)) {
  220.     Utils_Bailout("CheckOptions: bad disk limit value.\n", BAIL_PRINT);
  221.     }
  222.     if (parmsPtr->test) {
  223.     if (strcmp(parmsPtr->netMask, DEF_NETMASK) != 0) {
  224.         Utils_Bailout("Test mode prohibits use of netmask\n", BAIL_PRINT);
  225.     }
  226.     if (gethostname(hostname, sizeof(hostname)) == -1) {
  227.         Utils_Bailout("gethostname", BAIL_PERROR);
  228.     }
  229.     if ((hostPtr=gethostbyname(hostname)) == NULL) {
  230.         Utils_Bailout("gethostbyname", BAIL_PERROR);
  231.     }
  232.     bcopy(hostPtr->h_addr_list[0], &hostaddr.s_addr, hostPtr->h_length);
  233.     parmsPtr->netMask = Str_Dup(inet_ntoa(hostaddr));
  234.     }
  235. }
  236.  
  237.  
  238. /*
  239.  *----------------------------------------------------------------------
  240.  *
  241.  * MakeRoot --
  242.  *
  243.  *    Create the top level directory, if it doesn't exist.
  244.  *
  245.  * Results:
  246.  *    none.
  247.  *
  248.  * Side effects:
  249.  *    Initializes the Jaquith files.
  250.  *
  251.  *----------------------------------------------------------------------
  252.  */
  253.  
  254. static void
  255. MakeRoot(rootName)
  256.     char *rootName;           /* name of index root */
  257. {
  258.     struct stat statBuf;
  259.     int retCode;
  260.     char pathName[T_MAXPATHLEN];
  261.  
  262.     errno = 0;
  263.     retCode = stat(rootName, &statBuf);
  264.     if ((retCode != -1) && (S_ISADIR(statBuf.st_mode))) {
  265.     sprintf(printBuf,"Checking directory %s: %s\n",
  266.         rootName, sys_errlist[errno]);
  267.     Log_Event("MakeRoot", printBuf, LOG_MINOR);
  268.     } else if ((retCode == -1) && (errno == ENOENT)) {
  269.     sprintf(printBuf, "Creating %s as the archive root\n", rootName);
  270.     retCode = mkdir(rootName, DEF_DIR_PERM);
  271.     Log_Event("MakeRoot", printBuf, LOG_MAJOR);
  272.     } else {
  273.     sprintf(printBuf,"Bad directory %s: %s\n",
  274.         pathName, sys_errlist[errno]);
  275.     Log_Event("MakeRoot", printBuf, LOG_FAIL);
  276.     exit(-1);
  277.     }
  278.  
  279.     strcpy(pathName, rootName);
  280.     strcat(pathName, "/freevols");
  281.     errno = 0;
  282.     retCode = stat(pathName, &statBuf);
  283.     if (retCode != -1) {
  284.     sprintf(printBuf,"Checking file %s: %s\n",
  285.         pathName, sys_errlist[errno]);
  286.     Log_Event("MakeRoot", printBuf, LOG_MINOR);
  287.     } else if ((retCode == -1) && (errno == ENOENT)) {
  288.     sprintf(printBuf, "Creating %s\n", pathName);
  289.     retCode = creat(pathName, DEF_PERM);
  290.     Log_Event("MakeRoot", printBuf, LOG_MAJOR);
  291.     } else {
  292.     sprintf(printBuf,"Bad file %s: %s\n",
  293.         pathName, sys_errlist[errno]);
  294.     Log_Event("MakeRoot", printBuf, LOG_FAIL);
  295.     exit(-1);
  296.     }
  297.  
  298.     strcpy(pathName, rootName);
  299.     strcat(pathName, "/");
  300.     strcat(pathName, DEF_DEFARCH);
  301.     strcat(pathName, ".arch");
  302.     errno = 0;
  303.     retCode = stat(pathName, &statBuf);
  304.     if ((retCode != -1) && (S_ISADIR(statBuf.st_mode))) {
  305.     sprintf(printBuf,"Checking directory %s: %s\n",
  306.         pathName, sys_errlist[errno]);
  307.     Log_Event("MakeRoot", printBuf, LOG_MINOR);
  308.     } else if ((retCode == -1) && (errno == ENOENT)) {
  309.     if (mkdir(pathName, DEF_DIR_PERM) != -1) {
  310.         sprintf(printBuf, "Creating directory %s\n", pathName);
  311.         Log_Event("MakeRoot", printBuf, LOG_MAJOR);
  312.     } else {
  313.         sprintf(printBuf, "Couldn't make directory %s\n", pathName);
  314.         Log_Event("MakeRoot", printBuf, LOG_FAIL);
  315.     }
  316.     } else {
  317.     sprintf(printBuf,"Bad directory %s: %s\n",
  318.         pathName, sys_errlist[errno]);
  319.     Log_Event("MakeRoot", printBuf, LOG_FAIL);
  320.     exit(-1);
  321.     }
  322.  
  323.     strcat(pathName, "/auth");
  324.     errno = 0;
  325.     retCode = stat(pathName, &statBuf);
  326.     if (retCode != -1) {
  327.     sprintf(printBuf,"Checking file %s: %s\n",
  328.         pathName, sys_errlist[errno]);
  329.     Log_Event("MakeRoot", printBuf, LOG_MINOR);
  330.     } else if ((retCode == -1) && (errno == ENOENT)) {
  331.     sprintf(printBuf, "Creating %s\n", pathName);
  332.     strcpy(pathName, rootName);
  333.     strcat(pathName, "/");
  334.     strcat(pathName, DEF_DEFARCH);
  335.     strcat(pathName, ".arch");
  336.     Admin_AddAuth(pathName, "root", "*", 'O');
  337.     Log_Event("MakeRoot", printBuf, LOG_MAJOR);
  338.     } else {
  339.     sprintf(printBuf,"Bad file %s: %s\n",
  340.         pathName, sys_errlist[errno]);
  341.     Log_Event("MakeRoot", printBuf, LOG_FAIL);
  342.     exit(-1);
  343.     }
  344.  
  345. }
  346.  
  347.  
  348.  
  349. /*
  350.  *----------------------------------------------------------------------
  351.  *
  352.  * StartManagers --
  353.  *
  354.  *    Read the manager list and start 'em running
  355.  *
  356.  * Results:
  357.  *    none.
  358.  *
  359.  * Side effects:
  360.  *    none.
  361.  *    
  362.  *----------------------------------------------------------------------
  363.  */
  364.  
  365. static void
  366. StartManagers()
  367. {
  368.     
  369. }
  370.  
  371.  
  372. /*
  373.  *----------------------------------------------------------------------
  374.  *
  375.  * InstallHandlers --
  376.  *
  377.  *    Install SIGCHLD handler.
  378.  *
  379.  * Results:
  380.  *    none.
  381.  *
  382.  * Side effects:
  383.  *    
  384.  *----------------------------------------------------------------------
  385.  */
  386.  
  387. static void
  388. InstallHandlers()
  389. {
  390.  
  391.     if (signal(SIGCHLD, SigChldHandler) == (void(*)()) -1) {
  392.     Utils_Bailout("signal", BAIL_PERROR);
  393.     }
  394.  
  395. } /* InstallHandlers */
  396.  
  397.  
  398. /*
  399.  *----------------------------------------------------------------------
  400.  *
  401.  * RemoveLocks --
  402.  *
  403.  *    Remove any dead lock files.
  404.  *
  405.  * Results:
  406.  *    None.
  407.  *
  408.  * Side effects:
  409.  *    Will perform unlink on the offending files.
  410.  *
  411.  *----------------------------------------------------------------------
  412.  */
  413.  
  414. static void
  415. RemoveLocks(root)
  416.     char *root;               /* root of tree */
  417. {
  418.     char pathName[T_MAXPATHLEN];
  419.     DIR *rootDirPtr;
  420.     DirObject *entryPtr;
  421.     struct stat unixStatBuf;
  422.  
  423.     if ((rootDirPtr=(DIR *)opendir(root)) == (DIR *) NULL) {
  424.     return;
  425.     }
  426.  
  427.     while ((entryPtr=readdir(rootDirPtr)) != (DirObject *)NULL) {
  428.     if (Str_Match(entryPtr->d_name, "*.arch")) {
  429.         strcpy(pathName, root);
  430.         strcat(pathName, "/");
  431.         strcat(pathName, entryPtr->d_name);
  432.         stat(pathName, &unixStatBuf);
  433.         if (S_ISADIR(unixStatBuf.st_mode)) {
  434.         Lock_RemoveAll(pathName, LOCK_RMCONFIRM);
  435.         }
  436.     }
  437.     }
  438.  
  439.     closedir(rootDirPtr);
  440.  
  441. }
  442.  
  443.  
  444.  
  445. /*
  446.  *----------------------------------------------------------------------
  447.  *
  448.  * PerformLoop --
  449.  *
  450.  *    Main command loop.
  451.  *
  452.  * Results:
  453.  *    None.
  454.  *
  455.  * Side effects:
  456.  *    Accepts connections from clients and handles command
  457.  *      messages to and from them.
  458.  *
  459.  *----------------------------------------------------------------------
  460.  */
  461.  
  462. static void
  463. PerformLoop(earSocket)
  464.     int earSocket;            /* socket Number */
  465. {
  466.     int i;
  467.     int numReady;
  468.     int retCode;
  469.     int newSocket;
  470.     fd_set readSet;
  471.     fd_set copySet;
  472.     TClient *clientPtr;
  473.  
  474.     FD_ZERO(&readSet);
  475.     FD_SET(earSocket,&readSet);
  476.  
  477.     sprintf(printBuf,"Start listening on port %d\n", parms.port);
  478.     Log_Event("PerformLoop", printBuf, LOG_MAJOR);
  479.  
  480.     while(1) {
  481.     copySet = readSet;
  482.     numReady = select(FD_SETSIZE, ©Set, (fd_set *)NULL, 
  483.               (fd_set *)NULL, (struct timeval *)NULL);
  484.     ReapChild();
  485.     if (numReady == -1) {
  486.         continue;        /* we were interrupted by a SIGCHLD */
  487.     }
  488.     for (i=0; i<FD_SETSIZE; i++) {
  489.         if ((i == earSocket) && (FD_ISSET(i, ©Set))) {
  490.         if ((newSocket=AddClient(earSocket)) != T_FAILURE) {
  491.             FD_SET(newSocket, &readSet);
  492.         }
  493.         } else if (FD_ISSET(i, ©Set)) {
  494.         clientPtr = FindClientBySocket(i);
  495.         retCode = ReadMsg(clientPtr);
  496.         if (retCode != T_ACTIVE) {
  497.             FD_CLR(i, &readSet);
  498.             if (retCode == T_SUCCESS) {
  499.             ProcessCmd(clientPtr);
  500.             } else {
  501.             SendMailResp(clientPtr, retCode, syserr);
  502.             DelClient(clientPtr);
  503.             }
  504.         }
  505.         }
  506.     }
  507.     MEM_REPORT("PerformLoop", ALLROUTINES, SORTBYOWNER);
  508.     }
  509.  
  510. }
  511.  
  512.  
  513. /*
  514.  *----------------------------------------------------------------------
  515.  *
  516.  * ReadMsg --
  517.  *
  518.  *    Obtain the msg header so we can determine what to do.
  519.  * Then read in the rest of the msg according to its type.
  520.  * Note: Due to timing, we cannot count on getting the whole header at
  521.  * once, so we have to be prepared to read it in pieces and build it.
  522.  *
  523.  * Results:
  524.  *    None.
  525.  *
  526.  * Side effects:
  527.  *    None.
  528.  *
  529.  *----------------------------------------------------------------------
  530.  */
  531.  
  532. static int
  533. ReadMsg(clientPtr)
  534.     TClient *clientPtr;       /* ptr to client */
  535. {
  536.     int retCode;
  537.  
  538.     if (clientPtr->msgBuf == (char *)NULL) {
  539.     Log_Event("ReadMsg", "reading msg hdr...\n", LOG_TRACE);
  540.     retCode = ReadMsgHdr(clientPtr);
  541.     } else {
  542.     Log_Event("ReadMsg", "reading msg body...\n", LOG_TRACE);
  543.     retCode = ReadMsgBody(clientPtr);
  544.     }
  545.     
  546.     return retCode;
  547.  
  548. }
  549.  
  550.  
  551. /*
  552.  *----------------------------------------------------------------------
  553.  *
  554.  * ReadMsgHdr --
  555.  *
  556.  *    Obtain and validate the msg header.
  557.  *
  558.  * Results:
  559.  *    Return code saying we've got the hdr, or still reading
  560.  *      pieces of it.
  561.  *
  562.  * Side effects:
  563.  *    none.
  564.  *
  565.  * Note: 
  566.  *      This whole thing is disgusting. It was an early routine
  567.  *      and should be rewritten.
  568.  *
  569.  *----------------------------------------------------------------------
  570.  */
  571.  
  572. static int
  573. ReadMsgHdr(clientPtr)
  574.     TClient *clientPtr;       /* ptr to client */
  575. {
  576.     int retCode = T_SUCCESS;
  577.     int readCnt;
  578.     int sock = clientPtr->socket;
  579.     T_ReqMsgHdr *reqPtr = &(clientPtr->hdr);
  580.  
  581.     readCnt = Sock_ReadSocket(sock);
  582.  
  583.     if (readCnt < 0) {
  584.     syserr = errno;
  585.     return T_IOFAILED;
  586.     } else if (readCnt > 0) {
  587.     return(T_ACTIVE);
  588.     }
  589.  
  590.     /* Verify the complete header */
  591.     if ((reqPtr->version=ntohl(reqPtr->version)) != MSGVERSION) {
  592.     retCode = T_BADVERSION;
  593.     }
  594.     if (((reqPtr->cmd=ntohl(reqPtr->cmd)) < 0) ||
  595.     (reqPtr->cmd >= T_MAXCMDS)) {
  596.     retCode = T_BADCMD;
  597.     }
  598.     if (((reqPtr->len=ntohl(reqPtr->len)) < 1) ||
  599.     (reqPtr->len > T_MAXMSGLEN)) {
  600.     retCode = T_BADMSGFMT;
  601.     }
  602.  
  603.     reqPtr->flags = ntohl(reqPtr->flags);
  604.  
  605.     if (CheckAuth(ntohl(reqPtr->ticket)) == T_FAILURE) {
  606.     retCode = T_NOACCESS;
  607.     }
  608.  
  609.     if (retCode != T_SUCCESS) {
  610.     Sock_SendRespHdr(sock, retCode, syserr);
  611.     } else {
  612.     clientPtr->msgBuf = (char *)MEM_ALLOC("ReadMsgHdr", reqPtr->len);
  613.     Sock_SetSocket(sock, clientPtr->msgBuf, reqPtr->len);
  614.     }
  615.  
  616.     return T_ACTIVE;
  617.  
  618. }
  619.  
  620.  
  621. /*
  622.  *----------------------------------------------------------------------
  623.  *
  624.  * ReadMsgBody --
  625.  *
  626.  *    Obtain the msg body. The size will depend on the len
  627.  *      field supplied in the header.
  628.  *
  629.  * Results:
  630.  *    None.
  631.  *
  632.  * Side effects:
  633.  *      None.
  634.  *
  635.  * Note: 
  636.  *      This whole thing is disgusting. It was an early routine
  637.  *      and should be rewritten.
  638.  *
  639.  *----------------------------------------------------------------------
  640.  */
  641.  
  642. static int
  643. ReadMsgBody(clientPtr)
  644.     TClient *clientPtr;       /* ptr to client */
  645. {
  646.     int readCnt;
  647.     int sock = clientPtr->socket;
  648.     int count;
  649.     char *arr[4];
  650.     static char fmt[5] = "CCCC";
  651.  
  652.     readCnt = Sock_ReadSocket(sock);
  653.     if (readCnt < 0) {
  654.     syserr = errno;
  655.     return T_IOFAILED;
  656.     } else if (readCnt > 0) {
  657.     return(T_ACTIVE);
  658.     }
  659.  
  660.     /* Ok, we've got the fixed part of the body. Parse it */
  661.     arr[0] = (char *)&clientPtr->userName;
  662.     arr[1] = (char *)&clientPtr->groupName;
  663.     arr[2] = (char *)&clientPtr->mailName;
  664.     arr[3] = (char *)&clientPtr->archName;
  665.     Sock_UnpackData(fmt, clientPtr->msgBuf, &count, arr);
  666.     if (!*clientPtr->archName) {
  667.     MEM_FREE("ReadMsgBody", clientPtr->archName);
  668.     clientPtr->archName = Str_Dup(parms.defArch);
  669.     }
  670.     clientPtr->msgPtr = clientPtr->msgBuf+count;
  671.     clientPtr->msgLen = clientPtr->hdr.len-count;
  672.  
  673.     return T_SUCCESS;
  674.  
  675. }
  676.  
  677.  
  678. /*
  679.  *----------------------------------------------------------------------
  680.  *
  681.  * AddClient --
  682.  *
  683.  *    Accept an incoming connection request.
  684.  *
  685.  * Results:
  686.  *    Returns updated readSet and descriptor count for select.
  687.  *
  688.  * Side effects:
  689.  *    None.
  690.  *
  691.  *----------------------------------------------------------------------
  692.  */
  693.  
  694. static int
  695. AddClient(earSocket)
  696.     int earSocket;            /* socket number */
  697. {
  698.     int newSocket;
  699.     struct sockaddr_in newName;
  700.     int nameLen = sizeof(struct sockaddr_in);
  701.     struct hostent *peerInfo;
  702.     TClient *clientPtr;
  703.     int hostLen;
  704.     int i;
  705.     char *hostAddr;
  706.  
  707.     if ((newSocket=accept(earSocket, &newName, &nameLen)) == -1) {
  708.     syserr = errno;
  709.     sprintf(printBuf,"accept failed: Errno %d\n", errno);
  710.     Log_Event("AddClient", printBuf, LOG_FAIL);
  711.     return T_FAILURE;
  712.     }
  713.     if ((peerInfo=gethostbyaddr((char *)&newName.sin_addr,
  714.                 sizeof(newName.sin_addr),
  715.                 AF_INET)) == (struct hostent *)NULL) {
  716.     syserr = errno;
  717.     sprintf(printBuf,"gethostbyaddr failed: Errno %d\n", errno);
  718.     Log_Event("AddClient", printBuf, LOG_FAIL);
  719.     close(newSocket);
  720.     return T_FAILURE;
  721.     }
  722.  
  723.     if (((hostAddr=inet_ntoa(newName.sin_addr)) == NULL) ||
  724.     (!Str_Match(hostAddr, parms.netMask)) ||
  725.     (ntohs(newName.sin_port) >= NUMPRIVPORTS)) {
  726.     sprintf(printBuf,"Access denied to %s (%s). Netmask = %s\n",
  727.         peerInfo->h_name, hostAddr, parms.netMask);
  728.     Log_Event("AddClient", printBuf, LOG_FAIL);
  729.     Sock_SendRespHdr(newSocket, T_NOACCESS, 0, 0);
  730.     close(newSocket);
  731.     return T_FAILURE;
  732.     }
  733.  
  734.     sprintf(printBuf, "Connection from %s (%s)\n",
  735.         peerInfo->h_name, hostAddr);
  736.     Log_Event("AddClient", printBuf, LOG_MAJOR);
  737.  
  738.     hostLen = strlen(peerInfo->h_name) + 1;
  739.     clientPtr =    (TClient *)MEM_ALLOC("AddClient", sizeof(TClient)+hostLen);
  740.     clientPtr->msgLen = 0;
  741.     clientPtr->msgBuf = (char *)NULL;
  742.     clientPtr->msgPtr = (char *)NULL;
  743.     clientPtr->archInfo = (QInfo *)NULL;
  744.     clientPtr->mailName = (char *)NULL;
  745.     clientPtr->hostName = (char *)clientPtr + sizeof(TClient);
  746.     strcpy(clientPtr->hostName, peerInfo->h_name);
  747.     clientPtr->socket = newSocket;
  748.     clientPtr->date = Time_GetCurDate();
  749.  
  750.     /* Allocate a table slot for the guy ... */
  751.     for (i=0; i<clientMax; i++) {
  752.     if (clientList[i] == (TClient *)NULL) break;
  753.     }
  754.  
  755.     /* temporary. should grow table */
  756.     if (i == clientMax) {
  757.     Log_Event("AddClient", "Client table full", LOG_FAIL);
  758.     close(newSocket);
  759.     return T_FAILURE;
  760.     }
  761.     clientList[i] = clientPtr;
  762.     clientPtr->indx = i;
  763.  
  764.     /* Finally, set socket state so we can read hdr in bits&pieces */
  765.     Sock_SetSocket(newSocket, (char *)&clientPtr->hdr,
  766.            sizeof (clientPtr->hdr));
  767.  
  768.     return(newSocket);
  769.  
  770. }
  771.  
  772.  
  773. /*
  774.  *----------------------------------------------------------------------
  775.  *
  776.  * ProcessCmd --
  777.  *
  778.  *    Fork a child for the command if possible, else enqueue.
  779.  *
  780.  * Results:
  781.  *    None.
  782.  *
  783.  * Side effects:
  784.  *    Either a new process, or an en-fattened queue.
  785.  *
  786.  *----------------------------------------------------------------------
  787.  */
  788.  
  789. static void
  790. ProcessCmd(clientPtr)
  791.     TClient *clientPtr;       /* ptr to client */
  792. {
  793.     char *archName = clientPtr->archName;
  794.     QInfo *infoPtr;
  795.  
  796.     if (clientPtr->hdr.cmd == T_CMDNULL) {
  797.     Sock_SendRespHdr(clientPtr->socket, T_SUCCESS, 0);
  798.     return;
  799.     }
  800.  
  801.     if ((infoPtr=FindQueueInfo(archName)) == (QInfo *)NULL) {
  802.     infoPtr = MakeQueueInfo(archName);
  803.     }
  804.     clientPtr->archInfo = infoPtr;
  805.  
  806.     if ((clientPtr->hdr.cmd != T_CMDPUT) ||
  807.     (infoPtr->activeWriter == (TClient *)NULL)) {
  808.     SpawnChild(clientPtr);
  809.     } else {
  810.     sprintf(printBuf, "Enqueue 0x%x slot %d for archive %s\n",
  811.         clientPtr, clientPtr->indx, clientPtr->archName);
  812.     Log_Event("ProcessCmd", printBuf, LOG_MAJOR);
  813.     Q_Add(infoPtr->qPtr,(Q_ClientData)clientPtr, Q_TAILQ);
  814.     }
  815.  
  816. }
  817.  
  818.  
  819. /*
  820.  *----------------------------------------------------------------------
  821.  *
  822.  * SpawnChild --
  823.  *
  824.  *    Fork a child to do something useful.
  825.  *
  826.  * Results:
  827.  *    None.
  828.  *
  829.  * Side effects:
  830.  *    none.
  831.  *
  832.  *----------------------------------------------------------------------
  833.  */
  834.  
  835. static void
  836. SpawnChild(clientPtr)
  837.     TClient *clientPtr;       /* ptr to client */
  838. {
  839.     int pid = 0;
  840.     char buf1[DECINTLEN+1];
  841.     char buf2[DECINTLEN+1];
  842.     char buf3[DECINTLEN+1];
  843.     char buf4[T_MAXSTRINGLEN];
  844.     char *progName;
  845.  
  846.     if (clientPtr->hdr.cmd == T_CMDPUT) {
  847.     clientPtr->archInfo->activeWriter = clientPtr;
  848.     }
  849.  
  850.     if ((pid=fork()) == -1) {
  851.     sprintf(printBuf,"fork failed: %s\n", sys_errlist[errno]);
  852.     Log_Event("SpawnChild", printBuf, LOG_FAIL);
  853.     return;
  854.     }
  855.  
  856.     if (pid == 0) {
  857.     sprintf(buf1, "%d", clientPtr->socket);
  858.     sprintf(buf2, "%d", clientPtr->hdr.flags);
  859.     sprintf(buf3, "%d", parms.fsyncFreq);
  860.     strcpy(buf4, clientPtr->archName);
  861.     strcat(buf4, ".arch");
  862.     progName = progList[clientPtr->hdr.cmd];
  863.     execlp(progName, progName,
  864.            "-socket", buf1,
  865.            "-archive", buf4,
  866.            "-flags", buf2,
  867.            "-root", parms.root,
  868.            "-disklow", parms.diskLow,
  869.            "-diskhigh", parms.diskHigh,
  870.            "-username", clientPtr->userName,
  871.            "-groupname", clientPtr->groupName,
  872.            "-hostname", clientPtr->hostName,
  873.            "-cleaner", parms.cleanExec,
  874.            "-fsyncfreq", buf3,
  875.            (parms.childDbg) ? "-debug" : " ",
  876.            NULL);
  877.     _exit(T_EXECFAILED);
  878.     } else {
  879.     sprintf(printBuf,"Spawn child 0x%x slot %d\n", 
  880.         pid, clientPtr->indx);
  881.     Log_Event("SpawnChild", printBuf, LOG_MINOR);
  882.     clientPtr->pid = pid;
  883.     close(clientPtr->socket);
  884.     clientPtr->socket = NO_SOCKET;
  885.     }
  886.  
  887. }
  888.  
  889.  
  890. /*
  891.  *----------------------------------------------------------------------
  892.  *
  893.  * DelClient --
  894.  *
  895.  *    Exorcise a client from list.
  896.  *
  897.  * Results:
  898.  *    None.
  899.  *
  900.  * Side effects:
  901.  *    None.
  902.  *
  903.  *----------------------------------------------------------------------
  904.  */
  905.  
  906. static void
  907. DelClient(clientPtr)
  908.     TClient *clientPtr;       /* ptr to client */
  909. {
  910.     int sock = clientPtr->socket;
  911.     int indx = clientPtr->indx;
  912.     QInfo *infoPtr = clientPtr->archInfo;
  913.  
  914.     sprintf(printBuf,"client 0x%x sock %d archInfo 0x%x\n",
  915.         clientPtr->pid, sock, infoPtr);
  916.     Log_Event("DelClient", printBuf, LOG_TRACE);
  917.  
  918.     if (sock != NO_SOCKET) {
  919.     close(sock);
  920.     }
  921.     if ((infoPtr != (QInfo *)NULL) && (infoPtr->activeWriter == clientPtr)) {
  922.         infoPtr->activeWriter = (TClient *)NULL;
  923.     }
  924.     if (clientPtr->msgBuf != (char *)NULL) {
  925.     MEM_FREE("DelClient", clientPtr->msgBuf);
  926.     }
  927.     MEM_FREE("DelClient", (char *)clientPtr->userName);
  928.     MEM_FREE("DelClient", (char *)clientPtr->groupName);
  929.     MEM_FREE("DelClient", (char *)clientPtr->mailName);
  930.     MEM_FREE("DelClient", (char *)clientPtr->archName);
  931.     MEM_FREE("DelClient", (char *)clientPtr);
  932.     clientList[indx] = (TClient *)NULL;
  933. }
  934.  
  935.  
  936. /*
  937.  *----------------------------------------------------------------------
  938.  *
  939.  * FindClientByPid --
  940.  *
  941.  *    Locate a client by pid.
  942.  *
  943.  * Results:
  944.  *    Index of desired client or -1 if not found.
  945.  *
  946.  * Side effects:
  947.  *    None.
  948.  *
  949.  *----------------------------------------------------------------------
  950.  */
  951.  
  952. static int
  953. FindClientByPid(pid)
  954.     int pid;                  /* process id */
  955. {
  956.     int i;
  957.  
  958.     for (i=0; i<MAXCLIENT; i++) {
  959.     if ((clientList[i] != (TClient *)NULL) &&
  960.         (clientList[i]->pid == pid)) {
  961.         sprintf(printBuf,"Found pid 0x%x, slot %d\n", pid, i);
  962.         Log_Event("FindClientByPid", printBuf, LOG_TRACE);
  963.         return i;
  964.     }
  965.     }
  966.  
  967.     return T_FAILURE;
  968. }
  969.  
  970.  
  971. /*
  972.  *----------------------------------------------------------------------
  973.  *
  974.  * FindClientBySocket --
  975.  *
  976.  *    Locate a client by socket.
  977.  *
  978.  * Results:
  979.  *    Ptr to client or NULL;
  980.  *
  981.  * Side effects:
  982.  *    None.
  983.  *
  984.  *----------------------------------------------------------------------
  985.  */
  986.  
  987. static TClient *
  988. FindClientBySocket(sock)
  989.     int sock;                 /* socket number */
  990. {
  991.     int i;
  992.  
  993.     for (i=0; i<MAXCLIENT; i++) {
  994.     if ((clientList[i] != (TClient *)NULL) &&
  995.         (clientList[i]->socket == sock)) {
  996.         sprintf(printBuf,"Found socket %d (0x%x), slot %d\n",
  997.             sock, clientList[i]->pid, i);
  998.         Log_Event("FindClientBySocket", printBuf, LOG_TRACE);
  999.         return clientList[i];
  1000.     }
  1001.     }
  1002.  
  1003.     return ((TClient *)NULL);
  1004. }
  1005.  
  1006.  
  1007. /*
  1008.  *----------------------------------------------------------------------
  1009.  *
  1010.  * FindQueueInfo -- 
  1011.  *
  1012.  *      Locate queue for archive
  1013.  *
  1014.  * Results:
  1015.  *    QUEUE pointer.
  1016.  *
  1017.  * Side effects:
  1018.  *      None, but uses global qList.
  1019.  *
  1020.  *----------------------------------------------------------------------
  1021.  */
  1022.  
  1023. static QInfo *
  1024. FindQueueInfo(archName)
  1025.     char *archName;           /* archive name */
  1026. {
  1027.     QInfo *infoPtr = qList;
  1028.  
  1029.     while (infoPtr != (QInfo *)NULL) {
  1030.     if (strcmp(infoPtr->name,archName) == 0) {
  1031.         sprintf(printBuf,"Found queue %s (0x%x)\n",
  1032.             archName, infoPtr);
  1033.         Log_Event("FindQueueInfo", printBuf, LOG_TRACE);
  1034.         return (infoPtr);
  1035.     }
  1036.     infoPtr = infoPtr->link;
  1037.     }
  1038.  
  1039.     return(NULL);
  1040. }
  1041.  
  1042.  
  1043. /*
  1044.  *----------------------------------------------------------------------
  1045.  *
  1046.  * MakeQueueInfo -- 
  1047.  *
  1048.  *      Create a queue for an archive.
  1049.  *
  1050.  * Results:
  1051.  *    None.
  1052.  *
  1053.  * Side effects:
  1054.  *      Q_Handle handle is put in global qList.
  1055.  *
  1056.  *----------------------------------------------------------------------
  1057.  */
  1058.  
  1059. static QInfo *
  1060. MakeQueueInfo(archName)
  1061.     char *archName;           /* archive name */
  1062. {
  1063.     QInfo *infoPtr;
  1064.  
  1065.     infoPtr = (QInfo *)MEM_ALLOC("MakeQueue",
  1066.                  sizeof(QInfo)+strlen(archName)+1);
  1067.     infoPtr->qPtr = Q_Create(archName, 0);
  1068.     infoPtr->name = (char *)infoPtr+sizeof(QInfo);
  1069.     infoPtr->activeWriter = (TClient *)NULL;
  1070.     strcpy(infoPtr->name,archName);
  1071.     infoPtr->link = qList;
  1072.     qList = infoPtr;
  1073.  
  1074.     sprintf(printBuf,"Made queue: %s 0x%x\n", archName, infoPtr);
  1075.     Log_Event("MakeQueueInfo", printBuf, LOG_MINOR);
  1076.  
  1077.     return (infoPtr);
  1078.  
  1079. }
  1080.  
  1081.  
  1082. /*
  1083.  *----------------------------------------------------------------------
  1084.  *
  1085.  * ReapChild
  1086.  *    Clean up upon child termination.
  1087.  *
  1088.  * Results:
  1089.  *    none.
  1090.  *
  1091.  * Side effects:
  1092.  *    Deallocates TClient structure
  1093.  *
  1094.  *----------------------------------------------------------------------
  1095.  */
  1096.  
  1097. static void
  1098. ReapChild()
  1099. {
  1100.     int pid;
  1101.     int indx;
  1102.     union wait wstatus;
  1103.     TClient *clientPtr;
  1104.     int oldmask;
  1105.     QInfo *infoPtr;
  1106.     
  1107.     oldmask = sigblock(sigmask(SIGCHLD));
  1108.     while (deadChild > 0) {
  1109.     pid = wait3(&wstatus, WNOHANG, NULL);
  1110.     if (pid == 0) {
  1111.         sprintf(printBuf,
  1112.             "wait3 returned 0 but deadChild is %d; resetting to 0\n",
  1113.             deadChild);
  1114.         Log_Event("ReapChild", printBuf, LOG_FAIL);
  1115.         deadChild = 0;
  1116.         break;
  1117.     } 
  1118.  
  1119.     deadChild--;
  1120.     sprintf(printBuf,"Child pid 0x%x status 0x%x; deadChild %d\n",
  1121.         pid, wstatus.w_status, deadChild);
  1122.     Log_Event("ReapChild",printBuf, LOG_TRACE);
  1123.  
  1124.     if ((indx=FindClientByPid(pid)) == T_FAILURE) {
  1125.         sprintf(printBuf,"Couldn't find child pid 0x%x\n", pid);
  1126.         Log_Event("ReapChild", printBuf, LOG_FAIL);
  1127.     } else {
  1128.         clientPtr = clientList[indx];
  1129.         SendMailResp(clientPtr, wstatus.w_status, syserr);
  1130.         infoPtr = clientPtr->archInfo;
  1131.         if (infoPtr == (QInfo *)NULL) {
  1132.         sprintf(printBuf,"No info for archive %s\n",
  1133.             clientPtr->archName);
  1134.         Log_Event("ReapChild", printBuf, LOG_FAIL);
  1135.         } else {
  1136.         DelClient(clientPtr);
  1137.         if ((Q_Count(infoPtr->qPtr) > 0) &&
  1138.             (infoPtr->activeWriter == (TClient *)NULL)) {
  1139.             clientPtr = (TClient *)Q_Remove(infoPtr->qPtr);
  1140.             SpawnChild(clientPtr);
  1141.         }
  1142.         }
  1143.     }
  1144.     }
  1145.     sigsetmask(oldmask);
  1146.  
  1147. }
  1148.  
  1149.  
  1150. /*
  1151.  *----------------------------------------------------------------------
  1152.  *
  1153.  * SigChldHandler
  1154.  *
  1155.  *    Catch SIGCHLD interrupts.
  1156.  *
  1157.  * Results:
  1158.  *    none.
  1159.  *
  1160.  * Side effects:
  1161.  *    Updates global counter which will be checked in PerformLoop.
  1162.  *
  1163.  *----------------------------------------------------------------------
  1164.  */
  1165.  
  1166. static void
  1167. SigChldHandler(signal)
  1168.     int signal;               /* signal type */
  1169. {
  1170.     deadChild++;
  1171.     sprintf(printBuf,"deadChild now %d\n",deadChild);
  1172.     Log_Event("SigChldHandler",printBuf, LOG_TRACE);
  1173.  
  1174. } /* SigChldHandler */
  1175.  
  1176.  
  1177.  
  1178. /*
  1179.  *----------------------------------------------------------------------
  1180.  *
  1181.  * SendMailResp --
  1182.  *
  1183.  *    Send response by mail if requested
  1184.  *
  1185.  * Results:
  1186.  *    none.
  1187.  *
  1188.  * Side effects:
  1189.  *    May invoke shell and mailer
  1190.  *
  1191.  *----------------------------------------------------------------------
  1192.  */
  1193.  
  1194. static void
  1195. SendMailResp(clientPtr, status, syserr)
  1196.     TClient *clientPtr;
  1197.     int status;
  1198.     int syserr;
  1199. {
  1200.     int retCode;
  1201.     static char *cmdName[T_MAXCMDS] =
  1202.     {"Null", "jls", "jput", "jget", "jstat"};
  1203.  
  1204.     if (*clientPtr->mailName) {
  1205.     sprintf(printBuf, "mailing response 0x%x,0x%x to %s\n",
  1206.         status, syserr, clientPtr->mailName);
  1207.     Log_Event("SendMailResp", printBuf, LOG_MINOR);
  1208.     sprintf(printBuf,
  1209.         "Jaquith %s request\n\tFrom: %s@%s\n\tDate: %s\ncomplete with status 0x%x, errno 0x%x\n",
  1210.         cmdName[clientPtr->hdr.cmd],
  1211.         clientPtr->userName, clientPtr->hostName,
  1212.         Time_CvtToString(&clientPtr->date),
  1213.         status, syserr);
  1214.     if (Utils_SendMail(clientPtr->mailName, printBuf, "response") != 0) {
  1215.         sprintf(printBuf, "Got return code %d trying to mail response %d,%d to %s\n",
  1216.             retCode, status, syserr, clientPtr->mailName);
  1217.         Log_Event("SendMailResp", printBuf, LOG_FAIL);
  1218.     }
  1219.     }
  1220.  
  1221. }
  1222.  
  1223.  
  1224. /*
  1225.  *----------------------------------------------------------------------
  1226.  *
  1227.  * CheckAuth --
  1228.  *
  1229.  *    Check a client's authorization ticket.
  1230.  *      Should use Kerberos eventually.
  1231.  *
  1232.  * Results:
  1233.  *     0 == ok; 1 == unauthorized.
  1234.  *
  1235.  * Side effects:
  1236.  *    None.
  1237.  *
  1238.  *----------------------------------------------------------------------
  1239.  */
  1240.  
  1241. static int
  1242. CheckAuth(ticket)
  1243.     AuthHandle ticket;        /* kerberos ticket */
  1244. {
  1245.     return T_SUCCESS;
  1246.  
  1247. }
  1248.  
  1249.